home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
news
/
readers
/
skim-0.8
/
skim-0
/
skim-0.8.4
/
VarBuf.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-02-18
|
13KB
|
552 lines
/*
* NAME
* VarBuf.c
* DESCRIPTION
* VarBuf is An Abstract Data Type which provides variable size memory
* buffers. A VarBuf grows and shrinks in size automatically. The caller does
* not have to take care of memory allocation. Operations and queries are
* available to use a VarBuf to store a variable size character string.
* COPYRIGHT
* VarBuf - Variable size buffer ADT.
* Copyright (C) 1996 Rene W.J. Pijlman
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* VERSION
* $Header: /home/rene/sys/CVS_MasterSourceRepository/skim/VarBuf.c,v 1.8 1996/02/16 23:10:55 rene Exp $
* Distributed with Skim version 0.8.4.
*/
#include "Types.h"
#include "VarBuf.h"
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include "MemAlloc.h"
#include "StandardIO.h"
#define CLASS_NAME "VarBuf"
#include "CheckForDebris.h"
/* The private attributes of a VarBuf. */
struct _VarBuf {
size_t Size;
void * Address;
};
#define VB_EXPAND_SIZE_FOR_LINE 80
#define VB_EXPAND_SIZE_FOR_FILE 4096
VarBuf VBCreate( void )
{
VarBuf Result;
Result = MemAlloc( sizeof( struct _VarBuf ) );
Result->Address = NULL;
Result->Size = 0;
IncrementObjectCount();
assert( VBIsOK(Result) );
return Result;
}
Boolean VBIsOK( VarBuf This )
{
return This != NULL &&
( (This->Size == 0) == (This->Address == NULL) );
}
VarBuf VBClone( VarBuf This )
{
VarBuf Result = VBCreate();
Result->Size = This->Size;
Result->Address = MemAlloc( This->Size );
memmove( Result->Address, This->Address, This->Size );
return Result;
}
void VBAppendString( VarBuf This, const char * String )
{
size_t StringLength;
size_t NewSize;
assert( This != NULL && String != NULL );
StringLength = strlen( String );
NewSize = This->Size + StringLength;
if ( NewSize > 0 )
{
This->Address = MemRealloc( This->Address, NewSize );
memcpy( This->Address + This->Size, String, StringLength );
}
This->Size = NewSize;
}
void VBAppendCharacter( VarBuf This, char c )
{
char String[2];
assert( This != NULL );
String[0] = c;
String[1] = '\0';
VBAppendString( This, String );
}
void VBAppendVB( VarBuf This, VarBuf Source )
{
size_t NewSize;
assert( This != NULL && Source != NULL );
NewSize = This->Size + Source->Size;
if ( NewSize > 0 )
{
This->Address = MemRealloc( This->Address, NewSize );
memcpy( This->Address + This->Size, Source->Address, Source->Size );
}
This->Size = NewSize;
}
void VBDestroy( VarBuf This )
{
if ( This != NULL )
{
MemFree( This->Address );
MemFree( This );
DecrementObjectCount();
}
}
void VBReadFile( VarBuf This, StandardIO IO )
{
assert( This != NULL );
assert( IO != NULL );
assert( SIOIsOpenForRead(IO) );
while ( !SIOEndOfFile(IO) )
{
This->Address = MemRealloc( This->Address,
This->Size + VB_EXPAND_SIZE_FOR_FILE );
This->Size += SIORead( IO, This->Address + This->Size,
VB_EXPAND_SIZE_FOR_FILE );
}
This->Address = MemRealloc( This->Address, This->Size );
}
void VBWriteFile( VarBuf This, StandardIO IO )
{
assert( This != NULL );
assert( IO != NULL );
assert( SIOIsOpenForWrite(IO) );
SIOWrite( IO, This->Address, This->Size );
}
/* Append one line from File and append to the VarBuf. */
Boolean VBReadLine( VarBuf This, StandardIO IO, Boolean IncludeLinefeed )
{
Boolean ReadSomeData = False;
Boolean MoreData = True;
size_t OldSize;
assert( This != NULL && IO != NULL );
OldSize = This->Size;
while ( MoreData )
{
This->Address = MemRealloc( This->Address,
This->Size + VB_EXPAND_SIZE_FOR_LINE );
SIOFileGetPartOfLine( IO, (char *)This->Address + This->Size,
VB_EXPAND_SIZE_FOR_LINE );
if ( SIOEndOfFile(IO) )
{
MoreData = False;
}
else
{
ReadSomeData = True;
This->Size += strlen( (char *)(This->Address + This->Size) );
MoreData = ((char *)This->Address)[ This->Size - 1] != '\n';
}
}
if( ReadSomeData )
{
if ( !IncludeLinefeed &&
((char *)This->Address)[ This->Size - 1] == '\n' )
{
This->Address = MemRealloc( This->Address, This->Size - 1 );
This->Size--;
}
}
else
{
/* Back to original size. */
This->Address = MemRealloc( This->Address, OldSize );
}
return ReadSomeData;
}
void * VBAddress( VarBuf This )
{
assert( This );
return This->Address;
}
size_t VBSize( VarBuf This )
{
assert( This != NULL );
return This->Size;
}
void VBReset( VarBuf This )
{
This->Address = MemRealloc( This->Address, 0 );
This->Size = 0;
}
/* This suffices for 32 and 64 bit architectures. */
#define MAXLEN_INTEGRAL_AS_STRING 20
/*
* The following subset of printf() conversion specifications is supported:
*
* %s : char *; print the null terminated string. Precision is not
* supported.
* %c : char; print one character.
* %d : integer.
* %u : unsigned integer.
* %ld : long.
* %lu : unsigned long.
* %% : Append one '%'.
*
* And the following extensions to the printf() conversion specifications are
* supported:
* %V : VarBuf. Print the contents of the VarBuf.
*/
void VBPrintfVA(
VarBuf This,
const char * FormatString,
va_list ArgumentPointer )
{
const char * p;
char NumberBuffer[ MAXLEN_INTEGRAL_AS_STRING + 1 ];
for ( p = FormatString; *p != '\0'; p++ )
{
if ( *p == '%' )
{
switch( *++p )
{
case 's':
VBAppendString( This, va_arg( ArgumentPointer, char * ) );
break;
case 'c':
VBAppendCharacter( This, va_arg( ArgumentPointer, char ) );
break;
case 'V':
VBAppendVB( This, va_arg( ArgumentPointer, VarBuf ) );
break;
case 'd':
sprintf( NumberBuffer, "%d",
va_arg( ArgumentPointer, int ) );
VBAppendString( This, NumberBuffer );
break;
case 'u':
sprintf( NumberBuffer, "%u",
va_arg( ArgumentPointer, unsigned int ) );
VBAppendString( This, NumberBuffer );
break;
case 'l':
switch( *++p )
{
case 'd':
sprintf( NumberBuffer, "%ld",
va_arg( ArgumentPointer, long ) );
VBAppendString( This, NumberBuffer );
break;
case 'u':
sprintf( NumberBuffer, "%lu",
va_arg( ArgumentPointer, unsigned long ) );
VBAppendString( This, NumberBuffer );
break;
default:
SIOPrintf( StandardError,
"Unknown conversion specification: %%l%c\n",
*p );
exit( EXIT_FAILURE );
break;
}
break;
case '%':
VBAppendCharacter( This, '%' );
break;
default:
SIOPrintf( StandardError,
"Unknown conversion specification: %%%c\n",
*p );
exit( EXIT_FAILURE );
break;
}
}
else
{
VBAppendCharacter( This, *p );
}
}
}
void VBPrintf( VarBuf This, const char * FormatString, ...)
{
va_list ArgumentPointer;
va_start( ArgumentPointer, FormatString );
VBPrintfVA( This, FormatString, ArgumentPointer );
va_end( ArgumenPointer );
}
char * VBAsString( VarBuf This )
{
/* Make null-terminated, but the '\0' is not part of the VarBuf. */
This->Address = MemRealloc( This->Address, This->Size + 1 );
((char *)This->Address)[This->Size] = '\0';
return This->Address;
}
void VBShiftLeft( VarBuf This, size_t Distance )
{
assert( This->Size >= Distance );
memmove( This->Address, This->Address + Distance, This->Size - Distance );
This->Address = MemRealloc( This->Address, This->Size - Distance );
This->Size = This->Size - Distance;
}
void VBShiftRight( VarBuf This, size_t Distance, char Pad )
{
This->Address = MemRealloc( This->Address, This->Size + Distance );
memmove( This->Address + Distance, This->Address, This->Size );
This->Size = This->Size + Distance;
memset( This->Address, (int)Pad, Distance );
}
void VBTruncate( VarBuf This, size_t NewSize )
{
assert( NewSize <= This->Size );
This->Address = MemRealloc( This->Address, NewSize );
This->Size = NewSize;
}
/* Make the buffer fixed size, by truncating or by appending characters. */
void VBFixSize( VarBuf This, size_t NewSize, char PadCharacter )
{
if ( This->Size < NewSize )
{
This->Address = MemRealloc( This->Address, NewSize );
while ( This->Size < NewSize )
{
((char *)This->Address)[This->Size++] = PadCharacter;
}
}
else if ( This->Size > NewSize )
{
VBTruncate( This, NewSize );
}
}
void VBRemoveLeadingBlanks( VarBuf This )
{
size_t NumberOfLeadingBlanks;
char * p;
for ( NumberOfLeadingBlanks = 0, p = ((char *)This->Address);
NumberOfLeadingBlanks < This->Size && isspace( *p );
p++ )
{
NumberOfLeadingBlanks++;
}
VBShiftLeft( This, NumberOfLeadingBlanks );
}
void VBRemoveTrailingBlanks( VarBuf This )
{
size_t NewSize;
char * p;
for ( NewSize = This->Size, p = ((char *)This->Address) + This->Size - 1;
NewSize > 0 && isspace( *p );
p-- )
{
NewSize--;
}
This->Address = MemRealloc( This->Address, NewSize );
This->Size = NewSize;
}
void VBSplitAtOffset(
VarBuf This,
size_t Offset,
VarBuf Part1,
VarBuf Part2 )
{
assert( This != NULL && Part1 != NULL && Part2 != NULL );
assert( Part1->Size == 0 && Part2->Size == 0 );
assert( This->Size >= Offset );
Part1->Address = MemRealloc( Part1->Address, Offset );
Part1->Size = Offset;
memmove( Part1->Address, This->Address, Part1->Size );
Part2->Address = MemRealloc( Part2->Address, This->Size - Offset );
Part2->Size = This->Size - Offset;
memmove( Part2->Address, ((char *)This->Address) + Offset, Part2->Size );
}
static VBCompareFunction StaticUserCompare;
static int Compare( const void * VB1, const void * VB2 )
{
return StaticUserCompare( *(VarBuf *)VB1, *(VarBuf *)VB2 );
}
void VBSortArrayOfVB(
VarBuf Array,
VBCompareFunction UserCompare )
{
StaticUserCompare = UserCompare;
qsort( Array->Address, Array->Size / sizeof (VarBuf),
sizeof (VarBuf), Compare );
}
void VBAppendBytes( VarBuf Array, void * Bytes, size_t size )
{
Array->Address = MemRealloc( Array->Address, Array->Size + size );
memmove( ((char *)Array->Address) + Array->Size, Bytes, size );
Array->Size += size;
}
void VBAppendVBReference( VarBuf Array, VarBuf Element )
{
VBAppendBytes( Array, &Element, sizeof(VarBuf) );
}
void VBAppendVoidPtr( VarBuf Array, void * Element )
{
VBAppendBytes( Array, &Element, sizeof(void *) );
}
Natural VBNumberOfLines( VarBuf This )
{
size_t i;
Natural NumberOfLines = 0;
for ( i = 0; i < This->Size; i++ )
{
if ( ((char *)This->Address)[i] == '\n' )
{
NumberOfLines++;
}
}
return NumberOfLines;
}
void VBEndWithNewline( VarBuf This )
{
if ( This->Size > 0 )
{
if ( ((char *)This->Address)[This->Size - 1] != '\n' )
{
VBAppendCharacter( This, '\n' );
}
}
}
VarBuf VBCreateString( const char * InitialString )
{
VarBuf New = VBCreate();
VBAppendString( New, InitialString );
return New;
}